#include "exportapi.h"

#include "bgfx/bgfx.h"

#include "app_loadtool.h"
#include "imgui_impl_bfgx.h"
//=================================Target========================================
struct Target
{
public:
	bgfx::TextureHandle     frametex;//frametex ���Sframebuffer һͬ�N��
	bgfx::FrameBufferHandle framebuffer;
	int width;
	int height;
};
EXPORT_API Target* Target_Create(int width, int height)
{
	auto texframe = bgfx::createTexture2D(width, height, false, 1, bgfx::TextureFormat::RGBA8, BGFX_TEXTURE_RT);
	auto texd16 = bgfx::createTexture2D(width, height, false, 1, bgfx::TextureFormat::D16, BGFX_TEXTURE_RT_WRITE_ONLY);
	bgfx::TextureHandle fbtextures[] = { texframe,texd16 };
	auto t = new Target();
	t->frametex = texframe;
	t->framebuffer = bgfx::createFrameBuffer(2, fbtextures, true);
	t->width = width;
	t->height = height;
	return { t };
}
EXPORT_API size_t Target_GetImGuiTexID(Target* handle)
{
	TexTagImGui tag;
	tag.handle = handle->frametex;
	tag.alphablend = true;
	tag.isMono = false;
	//uint32_t mem = 0;
	//((uint16_t*)&mem)[0] = handle->frametex.idx;
	//((uint8_t*)&mem)[2] = 1;//1 =IMGUI_FLAGS_ALPHA_BLEND
	//((uint8_t*)&mem)[3] = 0;
	return ((uint32_t*)&tag)[0];
}
EXPORT_API void Target_Destory(Target* handle)
{
	bgfx::destroy(handle->framebuffer);
	handle->framebuffer = BGFX_INVALID_HANDLE;
	handle->frametex = BGFX_INVALID_HANDLE;
	delete handle;
}
EXPORT_API  void Target_Reset(Target* handle, int width, int height)
{
	if (bgfx::isValid(handle->framebuffer))
	{
		if (width == handle->width && height == handle->height)
		{
			//donothing
		}
		else
		{
			bgfx::destroy(handle->framebuffer);
			handle->framebuffer = BGFX_INVALID_HANDLE;
			handle->frametex = BGFX_INVALID_HANDLE;
		}
	}
	if (!bgfx::isValid(handle->framebuffer))
	{
		auto texframe = bgfx::createTexture2D(width, height, false, 1, bgfx::TextureFormat::RGBA8, BGFX_TEXTURE_RT);
		auto texd16 = bgfx::createTexture2D(width, height, false, 1, bgfx::TextureFormat::D16, BGFX_TEXTURE_RT_WRITE_ONLY);
		bgfx::TextureHandle fbtextures[] = { texframe,texd16 };
		handle->frametex = texframe;
		handle->framebuffer = bgfx::createFrameBuffer(2, fbtextures, true);
		handle->width = width;
		handle->height = height;
	}
}
EXPORT_API void MainScreen_Reset(int width, int height)
{
	bgfx::reset(width, height);
}

//================================================================================Frame==============================================
//bgfx ��view�OӋ,һ��view ��һ���L�u��
//��bgfx��clear����һ���L�u�ĿG��B������һ���L�uֻ����һ��clear
//�@���OӋ�Ǻ����ģ���������҂���Ҫ�����@һ�c���tClear��׃����һ���ָ�ɴ��L�u���^��
int fviewid;
Target* target;

EXPORT_API void Frame_Clear(uint32_t color, bool withColor, bool withDepth)
{
	fviewid++;

	if (!withColor && !withDepth)
		return;
	uint16_t flag = 0;
	if (withColor)flag |= BGFX_CLEAR_COLOR;
	if (withDepth)flag |= BGFX_CLEAR_DEPTH;

	if (target != NULL)
	{
		bgfx::setViewFrameBuffer(fviewid, target->framebuffer);
		bgfx::setViewRect(fviewid, 0, 0, target->width, target->height);
	}
	else
	{
		auto w = bgfx::getStats()->width;
		auto h = bgfx::getStats()->height;
		bgfx::setViewFrameBuffer(fviewid, BGFX_INVALID_HANDLE);
		bgfx::setViewRect(fviewid, 0, 0, w, h);
	}
	bgfx::setViewClear(fviewid, flag, color);
	bgfx::touch(fviewid);
}
EXPORT_API void Frame_SetTarget(Target* handle)
{
	target = handle;
	fviewid = -1;
}
EXPORT_API void Frame_SetMainScreen()
{
	target = NULL;
	fviewid = -1;
}

EXPORT_API void Frame_Flush()
{
	bgfx::frame();
	fviewid = -1;
}
//===============================Texture==============================================
struct Texture
{
	bgfx::TextureHandle tex;
	int width;
	int height;
};
EXPORT_API Texture* Texture_LoadFromFile(const char16_t* filename)
{
	Texture* obj = new Texture();
	obj->tex = __LoadTexture(filename, obj->width, obj->height);
	return{ obj };
}
EXPORT_API Texture* Texture_LoadFromMem(const char* mem, uint32_t size)
{
	Texture* obj = new Texture();
	obj->tex = __loadTextureFromMem(mem, size, obj->width, obj->height);
	return{ obj };
}
EXPORT_API Texture* Texture_Create(uint32_t width, uint32_t height, const char* memInit)
{
	Texture* obj = new Texture();
	obj->width = width;
	obj->height = height;

	const bgfx::Memory* _mem = memInit == nullptr ? 0 : bgfx::makeRef(memInit, width * height * 4);
	obj->tex = bgfx::createTexture2D(width, height, false, 1, bgfx::TextureFormat::RGBA8, BGFX_TEXTURE_NONE, _mem);
	return{ obj };

}
EXPORT_API void Texture_Upload(Texture* texture, XYWH xywh, const char* mem, int size, int pitch)
{
	const bgfx::Memory* _mem = bgfx::makeRef(mem, size);
	bgfx::updateTexture2D(texture->tex, 0, 0, xywh.x, xywh.y, xywh.w, xywh.h, _mem, pitch);
}
EXPORT_API void Texture_Destory(Texture* handle)
{
	bgfx::destroy(handle->tex);
	handle->tex = BGFX_INVALID_HANDLE;
	delete handle;
}
EXPORT_API size_t Texture_GetImGuiTexID(Texture* handle)
{
	TexTagImGui tag;
	tag.handle = handle->tex;
	tag.alphablend = true;
	tag.isMono = false;
	return ((uint32_t*)&tag)[0];


}

//=============================================Material һ��
#include <map>
#include <string>
#include <memory>
#include <vector>
#include "bgfx/bgfx.h"
#include "../stringtool/stringconv.h"
struct Uniform
{
	bgfx::UniformHandle handle;
	size_t namehash;
	uint16_t num;
	UniformType type;
};

struct Program
{
	bgfx::ProgramHandle program;
	bgfx::ShaderHandle shaderVertex;
	bgfx::ShaderHandle shaderFragment;
	std::vector<Uniform> uniforms;
	enum class CullOption :uint64_t
	{
		NONE = 0,
		CW = UINT64_C(0x0000001000000000), //!< Cull clockwise triangles.
		CCW = UINT64_C(0x0000002000000000),//!< Cull counter-clockwise triangles.
	};
	enum class ZTestOption :uint64_t
	{
		LESS = UINT64_C(0x0000000000000010),
		LEQUAL = UINT64_C(0x0000000000000020),
		EQUAL = UINT64_C(0x0000000000000030),
		GEQUAL = UINT64_C(0x0000000000000040),
		GREATER = UINT64_C(0x0000000000000050),
		NOTEQUAL = UINT64_C(0x0000000000000060),
		NEVER = UINT64_C(0x0000000000000070),
		ALWAYS = UINT64_C(0x0000000000000080),

	};
	enum class BlendOption :uint64_t
	{
		ZERO = UINT64_C(0x0000000000001000),//!< 0, 0, 0, 0
		ONE = UINT64_C(0x0000000000002000),//!< 1, 1, 1, 1
		SRC_COLOR = UINT64_C(0x0000000000003000), //!< Rs, Gs, Bs, As
		INV_SRC_COLOR = UINT64_C(0x0000000000004000), //!< 1-Rs, 1-Gs, 1-Bs, 1-As
		SRC_ALPHA = UINT64_C(0x0000000000005000),//!< As, As, As, As
		INV_SRC_ALPHA = UINT64_C(0x0000000000006000),//!< 1-As, 1-As, 1-As, 1-As
		DST_ALPHA = UINT64_C(0x0000000000007000), //!< Ad, Ad, Ad, Ad
		INV_DST_ALPHA = UINT64_C(0x0000000000008000),//!< 1-Ad, 1-Ad, 1-Ad ,1-Ad
		DST_COLOR = UINT64_C(0x0000000000009000), //!< Rd, Gd, Bd, Ad
		INV_DST_COLOR = UINT64_C(0x000000000000a000), //!< 1-Rd, 1-Gd, 1-Bd, 1-Ad
		SRC_ALPHA_SAT = UINT64_C(0x000000000000b000), //!< f, f, f, 1; f = min(As, 1-Ad)
		FACTOR = UINT64_C(0x000000000000c000), //!< Blend factor
		INV_FACTOR = UINT64_C(0x000000000000d000),//!< 1-Blend factor

	};
	enum class PrimitvieTypeOption :uint64_t
	{
		TRILIST = 0,
		TRISTRIP = UINT64_C(0x0001000000000000), //!< Tristrip.
		LINES = UINT64_C(0x0002000000000000),//!< Lines.
		LINESTRIP = UINT64_C(0x0003000000000000), //!< Line strip.
		POINTS = UINT64_C(0x0004000000000000),//!< Points.
	};

	uint64_t state = 0;
	void SetDefault()
	{
		SetWriteMask(true, true, true, true, true);
		SetZTestFunc(ZTestOption::LESS);
		SetAlphaBlend(BlendOption::ONE, BlendOption::ZERO, BlendOption::ONE, BlendOption::ZERO);
		SetCull(CullOption::CW);
		SetPrimitiveType(PrimitvieTypeOption::TRILIST);
		SetMSAA(true);
	}
	void SetWriteMask(bool r, bool g, bool b, bool a, bool z)
	{
		state &= ~(uint64_t)BGFX_STATE_WRITE_MASK;

		if (r)state |= BGFX_STATE_WRITE_R;
		if (g)state |= BGFX_STATE_WRITE_G;
		if (b)state |= BGFX_STATE_WRITE_B;
		if (a)state |= BGFX_STATE_WRITE_A;
		if (z)state |= BGFX_STATE_WRITE_Z;
	}
	void SetZTestFunc(ZTestOption zfunc)
	{
		state &= ~(uint64_t)BGFX_STATE_DEPTH_TEST_MASK;
		state |= (uint64_t)zfunc;
	}
	void SetAlphaBlend(BlendOption srcRgb, BlendOption dstRgb, BlendOption srcA, BlendOption dstA)
	{
		state &= ~(uint64_t)BGFX_STATE_BLEND_MASK;
		state |= BGFX_STATE_BLEND_FUNC_SEPARATE((uint64_t)srcRgb, (uint64_t)dstRgb, (uint64_t)srcA, (uint64_t)dstA);
	}
	void SetCull(CullOption cull)
	{
		state &= ~(uint64_t)BGFX_STATE_CULL_MASK;
		state |= (uint64_t)cull;
	}
	void SetPrimitiveType(PrimitvieTypeOption type)
	{
		state &= ~(uint64_t)BGFX_STATE_PT_MASK;
		state |= (uint64_t)type;
	}
	void SetMSAA(bool enable)
	{
		if(!enable)
			state &= ~(uint64_t)BGFX_STATE_MSAA;
		else
			state |= (uint64_t)BGFX_STATE_MSAA;
	}

	~Program()//����
	{
		bgfx::destroy(this->program);
		this->program = BGFX_INVALID_HANDLE;
		this->shaderFragment = BGFX_INVALID_HANDLE;
		this->shaderVertex = BGFX_INVALID_HANDLE;
	}
};

struct Material
{
	std::shared_ptr<Program> prog;
};

std::map<size_t, std::shared_ptr<Program>> mapProgram;
std::shared_ptr<Program> _Program_Get(const char16_t* shadername)
{
	std::u16string str = shadername;
	std::hash<std::u16string> u16hash;
	size_t hash = u16hash(str);
	auto it = mapProgram.find(hash);
	if (it != mapProgram.end())
		return it->second;
	else
	{
		std::shared_ptr<Program> ptr(new Program());
		mapProgram[hash] = ptr;


		ptr->shaderVertex = __LoadShader(u"vs_cubes.bin");
		ptr->shaderFragment = __LoadShader(u"fs_cubes.bin");
		ptr->program = bgfx::createProgram(ptr->shaderVertex, ptr->shaderFragment, true);
		ptr->SetDefault();
		//collect shaderinfo
		bgfx::UniformHandle handlearray[256];
		int countVS = bgfx::getShaderUniforms(ptr->shaderVertex, handlearray, 256);
		int countFS = bgfx::getShaderUniforms(ptr->shaderFragment, handlearray + countVS, 256 - countVS);
		bgfx::UniformInfo info;
		for (auto i = 0; i < countVS + countFS; i++)
		{
			bgfx::getUniformInfo(handlearray[i], info);
			std::u16string uname = StringConv::ToUtf16String(info.name);
			Uniform u;
			u.handle = handlearray[i];
			u.namehash = u16hash(uname);
			u.num = info.num;
			u.type = (UniformType)info.type;
			ptr->uniforms.push_back(u);
		}
		return ptr;
	}
}
//int _Program_GetUniformCount(std::shared_ptr<Program> program)
//{
//	bgfx::UniformHandle handlearray[256];
//	int countVS = bgfx::getShaderUniforms(program->shaderVertex, handlearray, 256);
//	int countFS = bgfx::getShaderUniforms(program->shaderFragment, handlearray + countVS, 256 - countVS);
//	bgfx::UniformInfo info;
//	for (auto i = 0; i < countVS + countFS; i++)
//	{
//		bgfx::getUniformInfo(handlearray[i], info);
//		info.
//	}
//	return countVS + countFS;
//}
EXPORT_API Material* Material_Create(const char16_t* shadername)
{
	Material* mat = new  Material();
	mat->prog = _Program_Get(shadername);
	return mat;
}
EXPORT_API void Material_Destory(Material* material)
{
	delete material;
}
EXPORT_API int Material_GetUniformCount(Material* material)
{
	return material->prog->uniforms.size();
}
EXPORT_API const char16_t* Material_GetUniformName(Material* material, int index)
{
	auto& u = material->prog->uniforms[index];

	bgfx::UniformInfo info;
	bgfx::getUniformInfo(u.handle, info);
	auto name = StringConv::ToUtf16String(info.name);
	return name.c_str();
}
EXPORT_API size_t Material_GetUniformNameHash(Material* material, int index)
{
	auto& u = material->prog->uniforms[index];
	return u.namehash;
}
EXPORT_API UniformType Material_GetUniformType(Material* material, int index)
{
	auto& u = material->prog->uniforms[index];
	return u.type;
}
EXPORT_API void Material_SetTexture(Material* material, int uniformID, Texture* texture)
{
	auto& u = material->prog->uniforms[uniformID];
	bgfx::setTexture(0, u.handle, texture->tex);
}
EXPORT_API void Material_SetVec4(Material* material, int uniformID, Vector4 value)
{
	auto& u = material->prog->uniforms[uniformID];
	bgfx::setUniform(u.handle, &value, u.num);
}

//=================================Mesh========================================
struct Mesh
{
	bgfx::VertexLayout layout;
	bgfx::VertexBufferHandle vb;
	bgfx::IndexBufferHandle ib;
	bool isDynamic;
	bgfx::DynamicVertexBufferHandle dynvb;
	bgfx::DynamicIndexBufferHandle dynib;


};
struct myvec
{
	float x;
	float y;
	float z;
	uint32_t m_argb;
};
static myvec s_cubeVertices[] =
{
	{-1.0f,  1.0f,  1.0f, 0x01010101 },//0
	{ 1.0f,  1.0f,  1.0f, 0xff0101ff },//1
	{-1.0f, -1.0f,  1.0f, 0x0101ff01 },//2
	{-1.0f, -1.0f,  1.0f, 0x0101ff01 },//2
	{ 1.0f,  1.0f,  1.0f, 0xff0101ff },//1
	{ 1.0f, -1.0f,  1.0f, 0xff01ffff },//3

	{-1.0f,  1.0f, -1.0f, 0x01ff0101 },//4
	{-1.0f, -1.0f, -1.0f, 0xffffff01 },//6
	{ 1.0f,  1.0f, -1.0f, 0xffff01ff },//5
	{ 1.0f,  1.0f, -1.0f, 0xffff01ff },//5
	{-1.0f, -1.0f, -1.0f, 0xffffff01 },//6
	{ 1.0f, -1.0f, -1.0f, 0xffffffff },//7


	{-1.0f,  1.0f,  1.0f, 0x01010101 },//0
	{-1.0f, -1.0f,  1.0f, 0x0101ff01 },//2
	{-1.0f,  1.0f, -1.0f, 0x01ff0101 },//4
	{-1.0f,  1.0f, -1.0f, 0x01ff0101 },//4
	{-1.0f, -1.0f,  1.0f, 0x0101ff01 },//2
	{-1.0f, -1.0f, -1.0f, 0xffffff01 },//6

	{ 1.0f,  1.0f,  1.0f, 0xff0101ff },//1
	{ 1.0f,  1.0f, -1.0f, 0xffff01ff },//5
	{ 1.0f, -1.0f,  1.0f, 0xff01ffff },//3
	{ 1.0f,  1.0f, -1.0f, 0xffff01ff },//5
	{ 1.0f, -1.0f, -1.0f, 0xffffffff },//7
	{ 1.0f, -1.0f,  1.0f, 0xff01ffff },//3

	{-1.0f,  1.0f,  1.0f, 0x01010101 },//0
	{-1.0f,  1.0f, -1.0f, 0x01ff0101 },//4
	{ 1.0f,  1.0f,  1.0f, 0xff0101ff },//1
	{-1.0f,  1.0f, -1.0f, 0x01ff0101 },//4
	{ 1.0f,  1.0f, -1.0f, 0xffff01ff },//5
	{ 1.0f,  1.0f,  1.0f, 0xff0101ff },//1

	{-1.0f, -1.0f,  1.0f, 0x0101ff01 },//2
	{ 1.0f, -1.0f,  1.0f, 0xff01ffff },//3
	{-1.0f, -1.0f, -1.0f, 0xffffff01 },//6
	{-1.0f, -1.0f, -1.0f, 0xffffff01 },//6
	{ 1.0f, -1.0f,  1.0f, 0xff01ffff },//3
	{ 1.0f, -1.0f, -1.0f, 0xffffffff },//7

};

static const uint16_t s_cubeTriList[] =
{
	0, 1, 2, // 0
	1, 3, 2,
	4, 6, 5, // 2
	5, 6, 7,
	0, 2, 4, // 4
	4, 2, 6,
	1, 5, 3, // 6
	5, 7, 3,
	0, 4, 1, // 8
	4, 5, 1,
	2, 3, 6, // 10
	6, 3, 7,
};
void __initLayout(Mesh* mesh, VertexFormat format)
{
	mesh->layout.begin()
		.add(bgfx::Attrib::Enum::Position, 3, bgfx::AttribType::Enum::Float, false);

	switch (format)
	{
	case	 VertexFormat::Pos_Color0:
		mesh->layout.add(bgfx::Attrib::Color0, 4, bgfx::AttribType::Enum::Uint8, true);
		break;
	case VertexFormat::Pos_UV0_Color0:
		mesh->layout.add(bgfx::Attrib::TexCoord0, 2, bgfx::AttribType::Enum::Float, false);
		mesh->layout.add(bgfx::Attrib::Color0, 4, bgfx::AttribType::Enum::Uint8, true);
		break;
	case VertexFormat::Pos_UV0_UV1_Color0_Color1:
		mesh->layout.add(bgfx::Attrib::TexCoord0, 2, bgfx::AttribType::Enum::Float, false);
		mesh->layout.add(bgfx::Attrib::TexCoord1, 2, bgfx::AttribType::Enum::Float, false);
		mesh->layout.add(bgfx::Attrib::Color0, 4, bgfx::AttribType::Enum::Uint8, true);
		mesh->layout.add(bgfx::Attrib::Color1, 4, bgfx::AttribType::Enum::Uint8, true);
	case VertexFormat::Pos_UV0_UV1_UV2_Color0_Color1_Color2:
		mesh->layout.add(bgfx::Attrib::TexCoord0, 2, bgfx::AttribType::Enum::Float, false);
		mesh->layout.add(bgfx::Attrib::TexCoord1, 2, bgfx::AttribType::Enum::Float, false);
		mesh->layout.add(bgfx::Attrib::TexCoord2, 2, bgfx::AttribType::Enum::Float, false);
		mesh->layout.add(bgfx::Attrib::Color0, 4, bgfx::AttribType::Enum::Uint8, true);
		mesh->layout.add(bgfx::Attrib::Color1, 4, bgfx::AttribType::Enum::Uint8, true);
		mesh->layout.add(bgfx::Attrib::Color2, 4, bgfx::AttribType::Enum::Uint8, true);
	case VertexFormat::Pos_UV0_UV1_UV2_UV3_Color0_Color1_Color2_Color3:
		mesh->layout.add(bgfx::Attrib::TexCoord0, 2, bgfx::AttribType::Enum::Float, false);
		mesh->layout.add(bgfx::Attrib::TexCoord1, 2, bgfx::AttribType::Enum::Float, false);
		mesh->layout.add(bgfx::Attrib::TexCoord2, 2, bgfx::AttribType::Enum::Float, false);
		mesh->layout.add(bgfx::Attrib::TexCoord3, 2, bgfx::AttribType::Enum::Float, false);
		mesh->layout.add(bgfx::Attrib::Color0, 4, bgfx::AttribType::Enum::Uint8, true);
		mesh->layout.add(bgfx::Attrib::Color1, 4, bgfx::AttribType::Enum::Uint8, true);
		mesh->layout.add(bgfx::Attrib::Color2, 4, bgfx::AttribType::Enum::Uint8, true);
		mesh->layout.add(bgfx::Attrib::Color3, 4, bgfx::AttribType::Enum::Uint8, true);
		break;
	default:
		break;
	}
	mesh->layout.end();
}
EXPORT_API Mesh* Mesh_CreateSample()
{
	Mesh* mesh = new Mesh();
	__initLayout(mesh, VertexFormat::Pos_Color0);
	mesh->layout
		.begin()
		.add(bgfx::Attrib::Enum::Position, 3, bgfx::AttribType::Enum::Float, false)
		.add(bgfx::Attrib::Enum::Color0, 4, bgfx::AttribType::Enum::Uint8, true)
		.end();
	mesh->isDynamic = false;
	mesh->vb = bgfx::createVertexBuffer(
		bgfx::makeRef(s_cubeVertices, sizeof(s_cubeVertices)), mesh->layout
	);

	mesh->ib = BGFX_INVALID_HANDLE;
	return mesh;

}

EXPORT_API Mesh* Mesh_Create(VertexFormat format, int vertexCount, int triCount, const char* memVB, const uint16_t* memIB)
{
	Mesh* mesh = new Mesh();
	mesh->isDynamic = false;
	__initLayout(mesh, format);
	mesh->vb = bgfx::createVertexBuffer(bgfx::makeRef(memVB, vertexCount * mesh->layout.m_stride), mesh->layout);
	if (memIB == nullptr)
	{
		mesh->ib = BGFX_INVALID_HANDLE;
	}
	else
	{
		mesh->ib = bgfx::createIndexBuffer(bgfx::makeRef(memIB, triCount * 3 * 2));
	}
	return mesh;

}
EXPORT_API void Mesh_Destory(Mesh* handle)
{
	if (bgfx::isValid(handle->vb))
		bgfx::destroy(handle->vb);
	if (bgfx::isValid(handle->ib))
		bgfx::destroy(handle->ib);
	if (bgfx::isValid(handle->dynvb))
		bgfx::destroy(handle->dynvb);
	if (bgfx::isValid(handle->dynib))
		bgfx::destroy(handle->dynib);
	handle->vb = BGFX_INVALID_HANDLE;
	handle->ib = BGFX_INVALID_HANDLE;
	handle->dynvb = BGFX_INVALID_HANDLE;
	handle->dynib = BGFX_INVALID_HANDLE;
	delete handle;
}
EXPORT_API int Mesh_GetVertexStride(Mesh* handle)
{
	return handle->layout.m_stride;
}
EXPORT_API Mesh* MeshDynamic_Create(VertexFormat format, int vertexCount, int triCount)
{
	Mesh* mesh = new Mesh();
	mesh->isDynamic = true;
	__initLayout(mesh, format);
	mesh->dynvb = bgfx::createDynamicVertexBuffer(vertexCount, mesh->layout);
	if (triCount <= 0)
	{
		mesh->dynib = BGFX_INVALID_HANDLE;
	}
	else
	{
		mesh->dynib = bgfx::createDynamicIndexBuffer(triCount * 3);
	}
	return mesh;
}

EXPORT_API void MeshDynamic_UploadVertex(Mesh* mesh, int VertexStart, int VertexCount, const char* mem)
{
	bgfx::update(mesh->dynvb, VertexStart, bgfx::makeRef(mem, mesh->layout.getStride() * VertexCount));

}
EXPORT_API void MeshDynamic_UploadIndex(Mesh* mesh, int IndexStart, int IndexCount, const uint16_t* indexdata)
{
	bgfx::update(mesh->dynib, IndexStart, bgfx::makeRef(indexdata, IndexCount * 2));
}

#include "bx/math.h"

float _g_time = 0;
EXPORT_API void Frame_Draw(Material* mat, Mesh* mesh)
{
	_g_time += 0.01f;

	const bx::Vec3 at = { 0.0f, 0.0f,   0.0f };
	const bx::Vec3 eye = { 0.0f, 0.0f, -35.0f };

	float view[16];
	bx::mtxLookAt(view, eye, at);

	float proj[16];
	bx::mtxProj(proj, 60.0f, float(1024) / float(1024), 0.1f, 100.0f, bgfx::getCaps()->homogeneousDepth);
	bgfx::setViewTransform(0, view, proj);

	float mtx[16];
	bx::mtxIdentity(mtx);
	bx::mtxRotateXY(mtx, _g_time + 1 * 0.21f, _g_time + 1 * 0.37f);
	//mtx[12] = -15.0f + float(xx) * 3.0f;
	//mtx[13] = -15.0f + float(yy) * 3.0f;
	//mtx[14] = 0.0f;

	// Set model matrix for rendering.
	bgfx::setTransform(mtx);

	if (mesh->isDynamic)
	{
		bgfx::setVertexBuffer(0, mesh->dynvb);
		if (bgfx::isValid(mesh->dynib))
			bgfx::setIndexBuffer(mesh->dynib);
	}
	else
	{
		bgfx::setVertexBuffer(0, mesh->vb);
		if (bgfx::isValid(mesh->ib))
			bgfx::setIndexBuffer(mesh->ib);
	}
	// Set render states.
	bgfx::setState(mat->prog->state);

	bgfx::submit(fviewid, mat->prog->program);


}